package xiong.copy.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ZipUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.w3c.dom.html.HTMLTableElement;
import xiong.copy.domain.ColumnInfo;
import xiong.copy.domain.GenConfig;
import xiong.copy.domain.vo.TableInfo;
import xiong.copy.exception.BadRequestException;
import xiong.copy.repository.ColumnInfoRepository;
import xiong.copy.service.GeneratorService;
import xiong.copy.utils.FileUtil;
import xiong.copy.utils.GenUtil;
import xiong.copy.utils.PageUtil;
import xiong.copy.utils.StringUtils;


import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
@Slf4j
public class GeneratorServiceImpl implements GeneratorService {

    @PersistenceContext
    private EntityManager em;

    private final ColumnInfoRepository columnInfoRepository;


    @Override
    public Object getTables() {
        //information_schema.tables 系统库.表信息
        //select database()当前数库表
        String sql = "select table_name ,create_time , engine, table_collation, table_comment from information_schema.tables " +
                "where table_schema = (select database()) " +
                "order by create_time desc";
        Query query= em.createNativeQuery(sql);
        return query.getResultList(); //这里不用List<Object >是为什么


    }

    /**
     * 传入int数组  start 和 End 值
     * startEnd[0]  与  startEnd[1]
     * */
    @Override
    public Object getTables(String name, int[] startEnd) {
        String sql = "select table_name ,create_time , engine, table_collation, table_comment from information_schema.tables " +
                "where table_schema = (select database()) " +
                "and table_name like :table order by create_time desc";
           Query query =em.createNativeQuery(sql);

            query.setFirstResult(startEnd[0]);
            ////设置查询的起始下标
            query.setFirstResult(startEnd[0]);
            //设置查询结果集的最大数量，返回Query实例
            query.setMaxResults(startEnd[1]-startEnd[0]);
            //绑定Parameter对象的值
            //需name 是否为空值
            query.setParameter("table",StringUtils.isNotBlank(name) ? ("%" + name + "%") : "%%");

            List result = query.getResultList();
            List<TableInfo> tableInfos = new ArrayList<>();

            //每条信息都是对象
            //但返回值是Object 不能直接让tableInfos接收  向下转型
            for (Object obj: tableInfos){
                Object[] arr = (Object[]) obj;
                tableInfos.add(new TableInfo(arr[0],arr[1],arr[2],arr[3],ObjectUtil.isNotEmpty(arr[4]) ? arr[4] : "-"));
            }


            String countSql = "select count(1) from information_schema.tables " +
                    "where table_schema = (select database()) and table_name like :table";

            Query queryCount = em.createNativeQuery(countSql);

            queryCount.setParameter("table",StringUtils.isBlank(name) ? ("%" + name + "%") : "%%" );

            //获取单个结果集 是id为160105的记录的统计数据
             Object totalElements = queryCount.getSingleResult();

             //分页工具
            //tableInfos 获取table信息的数组
            //getSingleResult   getSingleResult
             return PageUtil.toPage(tableInfos,totalElements);
    }

    @Override
    public List<ColumnInfo> getColumns(String name) {
        //查找数据库中ColumnInfo 表的信息
        List<ColumnInfo> columnInfos = columnInfoRepository.findByTableNameOrderByIdAsc(name);

        //用hutool的集合判断工具
        //if 不为空 返回list
        //else  调用 query()  将结果保存到数据库
        if (CollectionUtil.isNotEmpty(columnInfos)){
            return columnInfos;
        }else {
            columnInfos = query(name);
            return columnInfoRepository.saveAll(columnInfos);
        }
    }

    @Override
    public List<ColumnInfo> query(String tableName) {
        String sql = "select column_name, is_nullable, data_type, column_comment, column_key, extra from information_schema.columns " +
                "where table_name = ? and table_schema = (select database()) order by ordinal_position";

            Query query = em.createNativeQuery(sql);
            query.setParameter(1,tableName);
            List result = query.getResultList();
            List<ColumnInfo> columnInfos = new ArrayList<>();

        for (Object object : result) {
            Object[] objs = (Object[]) object;
            columnInfos.add(new ColumnInfo(
                tableName,
               objs[0].toString(),
               "NO".equals(objs[1]),
                    objs[2].toString(),
                    ObjectUtil.isNotNull(objs[3]) ? objs[3].toString():null,
                    ObjectUtil.isNotNull(objs[4]) ? objs[4].toString():null,
                    ObjectUtil.isNotNull(objs[5]) ? objs[5].toString():null
            ));

        }


        return columnInfos;
    }
    /**
     * 数据库字段名称
     * @param columnInfoList   数据库中字段集合
     * @param columnInfos    程序中字段集合
     * */
    @Override
    public void sync(List<ColumnInfo> columnInfos, List<ColumnInfo> columnInfoList) {
        for (ColumnInfo columnInfo : columnInfoList){
            List<ColumnInfo> columns = columnInfos
                    .stream()
                    //过滤 取出 从columnInfos 取出与 columnInfoList 的数据库字段名称相同的
                    .filter(c->c.getColumnName().equals(columnInfo.getColumnName()))
                    //可以收集流中的数据到【集合】或者【数组】中去。
                    .collect(Collectors.toList());
            // 如果能找到，就修改部分可能被字段
            if (CollectionUtil.isNotEmpty(columns)){
                //只改变部分，所以随便获取一个
                ColumnInfo col = columns.get(0);
//                ColumnInfo col = new ColumnInfo();
                col.setColumnType(columnInfo.getColumnType());
                col.setExtra(columnInfo.getExtra());
                col.setKeyType(columnInfo.getKeyType());
                if (StringUtils.isNotBlank(columnInfo.getRemark())){
                    col.setRemark(columnInfo.getRemark());
                }
               columnInfoRepository.save(col);
            }else {
                // 如果找不到，则保存新字段信息
                columnInfoRepository.save(columnInfo);
            }

        }//修改数据库中字段

        //删除数据库字段

        for (ColumnInfo columnInfo : columnInfos) {
            // 根据字段名称查找
            List<ColumnInfo> columns = columnInfoList
                    .stream()
                    .filter(c -> c.getColumnName().equals(columnInfo.getColumnName()))
                    .collect(Collectors.toList());
            // 如果找不到，就代表字段被删除了，则需要删除该字段
            if (CollectionUtil.isEmpty(columns)){
                columnInfoRepository.delete(columnInfo);
            }
        }



    }

    @Override
    public void save(List<ColumnInfo> columnInfos) {
        columnInfoRepository.saveAll(columnInfos);
    }



    @Override
    public void generator(GenConfig genConfig, List<ColumnInfo> columns) {
        if (genConfig.getId() == null){
            throw  new BadRequestException("请先配置生成器");
        }

        try {
            GenUtil.generatorCode(columns, genConfig);
        } catch (IOException e) {
            log.error(e.getMessage(), e);
            throw new BadRequestException("生成失败，请手动处理已生成的文件");
        }



    }

    @Override
    public ResponseEntity<Object> preview(GenConfig genConfig, List<ColumnInfo> columns) {
        if (genConfig.getId() == null) {
            throw new BadRequestException("请先配置生成器");
        }

        List<Map<String, Object>> genList = GenUtil.preview(columns, genConfig);
        //返回List<Map<String, Object>>
        return new ResponseEntity<>(genList, HttpStatus.OK);
    }

    @Override
    public void download(GenConfig genConfig, List<ColumnInfo> columns, HttpServletRequest request, HttpServletResponse response) {
        if (genConfig.getId() == null) {
            throw new BadRequestException("请先配置生成器");
        }
        try {
            File file = new File(GenUtil.download(columns, genConfig));
            String zipPath = file.getPath() + ".zip";
            ZipUtil.zip(file.getPath(), zipPath);
            FileUtil.downloadFile(request, response, new File(zipPath), true);
        } catch (IOException e) {
            throw new BadRequestException("打包失败");
        }




    }


}
